package client;

import common.Constant;
import common.Message;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.net.Socket;

public class Client {
    private JFrame frame;
    private Socket socket = null;
    private BufferedReader bufferedReader = null;
    private PrintWriter printWriter = null;

    public Client() {
        try {
            socket = new Socket(Constant.serverIp, Constant.port);
            bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
        } catch (Exception e) {
            //nullpointerexception
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, "无法连接服务器");
            return;
        }
        setLayout();
        this.show();
    }

    private void setLayout() {
        frame = new JFrame("Register");
        frame.setBounds(600, 300, 350, 200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLayout(null);

        JPanel panel = new JPanel();
        panel.setBounds(0, 0, 350, 200);
        frame.getContentPane().add(panel);
        panel.setLayout(null);

        JLabel userLabel = new JLabel("username:");
        userLabel.setBounds(10, 20, 80, 25);
        panel.add(userLabel);
        JTextField userText = new JTextField(20);
        userText.setBounds(100, 20, 165, 25);
        panel.add(userText);

        JButton loginButton = new JButton("register");
        loginButton.setBounds(100, 100, 80, 25);
        panel.add(loginButton);
        loginButton.addActionListener(e -> {
            loginButton.setEnabled(false);
            String name = userText.getText();
            String s = Constant.encodeRegister(name);
            //发到server
            printWriter.println(s);
            //IO操作
            printWriter.flush();
            try {
                //等待响应
                s = bufferedReader.readLine();
            } catch (Exception ee) {
                ee.printStackTrace();
            }
            if (!s.equals(Constant.REGISTER_SUCCEED)) {
                JOptionPane.showMessageDialog(null, "Registration failed, username is occupied");
            } else {
                JOptionPane.showMessageDialog(null, "Welcome "+name);
                new Thread(new Dialog(name, socket)).start();
                close();
            }
            loginButton.setEnabled(true);
        });

        // 窗体关闭时关闭socket等等(release)
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                release();
            }
        });
    }

    public void show() {
        frame.setVisible(true);
    }

    public void close() {
        frame.dispose();
    }

    private void release() {
        try {
            if (socket != null) {
                socket.close();
            }
            if (printWriter != null) {
                printWriter.close();
            }
            if (bufferedReader != null) {
                bufferedReader.close();
            }
        } catch (Exception ee) {
            ee.printStackTrace();
        }
    }

    public static void main(String[] args){
        new Client();
    }
}

class Dialog implements Runnable {
    private JFrame frame;
    private JTextArea textArea1 = new JTextArea();  // 这个textArea用于显示聊天信息，不可编辑
    private String name;
    private Socket socket = null;
    private BufferedReader bufferedReader = null;
    private PrintWriter printWriter = null;

    public Dialog(String name, Socket socket) {
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, "无法连接服务器");
            return;
        }
        this.name = name;
        setLayout();
        this.show();
    }

    private void add(String s) {
        textArea1.append(s + "\r\n");
        textArea1.selectAll();
    }

    @Override
    public void run() {
        // 不停读取服务器传来的Message，然后添加到textArea1中
        String s = "";
        while (true) {
            try {
                s = bufferedReader.readLine();
            } catch (Exception e) {
                System.out.println("关闭了连接");
                close();
                break;
            }
            if (s.contains(Constant.MESSAGE)) {
                add(Constant.decodeMessage(s).toString());
            }
        }
    }

    private void setLayout() {
        frame = new JFrame(name);
        int height = 400;
        int width = 600;
        frame.setBounds(600, 300, width, height);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLayout(null);

        textArea1.setEditable(false);
        JScrollPane scrollPane1 = new JScrollPane(textArea1);
        JTextArea textArea2 = new JTextArea();
        JScrollPane scrollPane2 = new JScrollPane(textArea2);

        textArea1.setFont(new Font("宋体", Font.PLAIN, 14));
        textArea2.setFont(new Font("宋体", Font.PLAIN, 14));
        JButton button = new JButton("发送");
        int showHeight = height * 3 / 4;
        int buttonLength = height - (showHeight + 2);
        scrollPane1.setBounds(0, 0, width, showHeight);
        scrollPane2.setBounds(0, showHeight + 2, width - buttonLength - 2, buttonLength);
        button.setBounds(width - buttonLength, height - buttonLength,
                buttonLength * 2 / 3, buttonLength / 3);

        frame.getContentPane().add(scrollPane1);
        frame.getContentPane().add(scrollPane2);
        frame.getContentPane().add(button);


        // 点击发送按钮时，向远程服务器发送输入信息（打包成Message后发送）
        button.addActionListener(e -> {
            String s = textArea2.getText();
            if("bye".equals(s)){
                release();
            }
            textArea2.setText("");
            printWriter.println(Constant.encodeMessage(new Message(name, s)));
            printWriter.flush();
        });


        // 窗体关闭时关闭socket等等(release)
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                release();
            }
        });

        // 键盘监听，按了ENTER后，向远程服务器发送输入信息（打包成Message后发送）
        textArea2.addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {
                int k = e.getKeyChar();
                if (k == KeyEvent.VK_ENTER) {
                    String s = textArea2.getText();
                    if("bye\n".equals(s)){
                        release();
                    }
                    textArea2.setText("");
                    printWriter.println(Constant.encodeMessage(new Message(name, s)));
                    printWriter.flush();
                }
            }
        });
    }

    public void show() {
        frame.setVisible(true);
    }

    public void close() {
        release();
        frame.dispose();
        System.exit(0);
    }

    private void release() {
        // 释放资源时同时通知远程服务器，注销当前用户
        if (printWriter != null) {
            printWriter.println(Constant.encodeLogout(name));
            printWriter.flush();
        }
        try {
            if (socket != null) {
                socket.close();
            }
            if (printWriter != null) {
                printWriter.close();
            }
            if (bufferedReader != null) {
                bufferedReader.close();
            }

        } catch (Exception ee) {
            ee.printStackTrace();
        }finally {
            System.exit(0);
        }
    }
}

